package com.luke.netty.sample;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.util.CharsetUtil;

import java.util.concurrent.TimeUnit;

/**
 * @Descrtption NettyServerChannelHandler
 * @Author luke
 * @Date 2020/4/29
 **/
public class NettyServerChannelHandler extends ChannelInboundHandlerAdapter {

    /**客户端连接成功事件*/
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("-----channelActive-------");
        System.out.println("客户端连接成功,address:"+ctx.channel().remoteAddress());
    }

    /**读取到客户端发送过来的数据*/
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("-----channelRead-------");
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("客户端消息："+byteBuf.toString(CharsetUtil.UTF_8));

        Channel channel = ctx.channel();
        ChannelPipeline pipeline = ctx.pipeline();
        EventLoop eventLoop = channel.eventLoop();//拿到所在的EventLoop
        eventLoop.execute(() -> {
            //执行任务
            //虽然可以异步执行任务，但是不建议执行耗时长的任务
            //会长时间阻塞当前的NIOEventLoop线程（I/O线程）
            //如果有耗时长的操作，应该开启业务线程池来执行
            try {
                System.out.println("正在处理任务。。。");
                TimeUnit.SECONDS.sleep(60);
                System.out.println("任务处理完成。。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        //NioEventLoop是一个事件轮询器（线程）
        //NioEventLoop包含了一个选择器Selector和一个任务队列TaskQueue
        //一个客户端连接SocketChannel会被注册到某个Selector中
        //由于注册到Selector中的客户端连接SocketChanel会有多个
        //所以每个NioEventLoop管理着多个SocketChannel
    }

    /**数据读取完毕*/
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("-----channelReadComplete-------");
        ByteBuf byteBuf = Unpooled.copiedBuffer("你好，我是服务器", CharsetUtil.UTF_8);
        ctx.writeAndFlush(byteBuf);
    }

    /**发生异常*/
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("-----exceptionCaught-------");
        ctx.close();
    }

}
